package com.launcher;

import com.launcher.decorator.Engine;
import com.launcher.decorator.Fairring;
import com.launcher.decorator.Stage;
import com.launcher.factory.RocketFactory;
import com.launcher.factory.SimpleRocketFactory;
import com.launcher.observer.LaunchObserver;
import com.launcher.observer.RocketLaunchChecker;
import org.hibernate.exception.SQLGrammarException;

import javax.swing.*;

import java.awt.Dimension;
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

/**
 * @author wouter
 *         Date: 2/12/13
 *         Time: 11:39 AM
 */
public class Application
{
	private JTextArea log = new JTextArea();
	private JScrollPane scrollLog = new JScrollPane();
	private static JButton createPayloadButton;

	public static void main(String args[])
	{
		new Application();
    }

    public Application() {
    	System.setOut(new PrintStream(new FilteredStream(new ByteArrayOutputStream())));
        generateFrame();
        append("Loading...\n");

        RocketFactory simpleRocketFactory = new SimpleRocketFactory();

        List<Stage> stages = getStages(simpleRocketFactory);
        fillStages(simpleRocketFactory, stages);

        List<Engine> engines = getEngines();
        fillEngines(simpleRocketFactory, stages, engines);

        List<PayLoad> payloads = getPayLoads();
        fillPayloads(simpleRocketFactory, payloads);
     
        Application.setEnabled(true);
    }
    
    public static void setEnabled(boolean b)
    {
    	Application.createPayloadButton.setEnabled(b);
    }

    private void fillPayloads(RocketFactory simpleRocketFactory, List<PayLoad> payloads) {
        if (payloads != null && payloads.size() == 0)
        {
            simpleRocketFactory.createPayLoad(200000000, 50, 2);
            simpleRocketFactory.createPayLoad(250000000, 80, 4);
            simpleRocketFactory.createPayLoad(400000000, 130, 6);
            simpleRocketFactory.createPayLoad(500000000, 140, 8);
            simpleRocketFactory.createPayLoad(650000000, 160, 8);
            simpleRocketFactory.createPayLoad(820000000, 180, 9);
            simpleRocketFactory.createPayLoad(1000000000, 200, 10);
        }
    }

    private void fillEngines(RocketFactory simpleRocketFactory, List<Stage> stages, List<Engine> engines) {
        if (engines != null && engines.size() == 0)
        {
            Engine engine = (Engine) simpleRocketFactory.createEngine(50000000, 750);
            engine.setRocketDecorator(stages.get(0));
            RocketService.getInstance().saveRocket(engine);

            engine = (Engine) simpleRocketFactory.createEngine(75000000, 1250);
            engine.setRocketDecorator(stages.get(1));
            RocketService.getInstance().saveRocket(engine);

            engine = (Engine) simpleRocketFactory.createEngine(100000000, 3250);
            engine.setRocketDecorator(stages.get(2));
            RocketService.getInstance().saveRocket(engine);
        }
    }

    private void fillStages(RocketFactory simpleRocketFactory, List<Stage> stages) {
        if (stages != null && stages.size() == 0)
		{
			stages.add((Stage) simpleRocketFactory.createStage(60000000, 120, 18));
			stages.add((Stage) simpleRocketFactory.createStage(70000000, 750, 25));
			stages.add((Stage) simpleRocketFactory.createStage(100000000, 1250, 42));
		}
    }

    private void startDoingStuffWithRockets() {
        RocketLaunchChecker rocketLaunchChecker = new RocketLaunchChecker();

        // create an observer
        LaunchObserver launchObserver = new LaunchObserver();

        // subscribe the observer to the event source
        rocketLaunchChecker.addObserver(launchObserver);

        // starts the event thread
        Thread thread = new Thread(rocketLaunchChecker);
        thread.start();

        RocketLauncher launcher = new RocketLauncher();

        Thread thread1 = new Thread(launcher);
        thread1.start();
    }

    private List<PayLoad> getPayLoads() {
        List<PayLoad> payloads = null;
        try
        {
            payloads = RocketService.getInstance().getPayLoads();
        }
        catch (SQLGrammarException e) {}
        return payloads;
    }

    private List<Engine> getEngines() {
        List<Engine> engines = null;
        try
        {
            engines = RocketService.getInstance().getEngines();
        }
        catch (SQLGrammarException e) {}
        return engines;
    }

    private List<Stage> getStages(RocketFactory simpleRocketFactory) {
        /**
         *  Use hibernate to fill the database, if empty
         */
        List<Fairring> fairrings = null;
        try
        {
            fairrings = RocketService.getInstance().getFairrings();
        }
        catch (SQLGrammarException e) {}

        if (fairrings != null && fairrings.size() == 0)
        {
            simpleRocketFactory.createFairring(1600000, 10, 10);
            simpleRocketFactory.createFairring(1000000, 5, 5);
        }

        List<Stage> stages = null;
        try
        {
            stages = RocketService.getInstance().getStages();
        }
        catch (SQLGrammarException e) {}
        return stages;
    }

    private JFrame generateFrame() {
        JFrame ui = new JFrame();
        ui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        ui.setSize(300, 300);
        ui.setLayout(new BorderLayout());
        ui.setTitle("ROCkET LAUNCHAH");
        ui.setVisible(true);

        createPayloadButton = new JButton("Launch " + RocketLauncher.getAmountToLaunch() + " Payloads");
        createPayloadButton.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent actionEvent) {
                    	clear();
                    	Application.setEnabled(false);
                        startDoingStuffWithRockets();
                    }
                }
        );
        Application.setEnabled(false);

        ui.add(createPayloadButton, BorderLayout.NORTH);

        log.setEditable(false);
		scrollLog.getViewport().add(log);
		scrollLog.setPreferredSize(new Dimension(300, 200));
		ui.add(scrollLog, BorderLayout.SOUTH);
        
        return ui;
    }
    
    private void append(String str)
    {
    	log.setEditable(true);
		log.append(str);
		log.setCaretPosition(log.getText().length());
		log.setEditable(false);
    }
    
    private void clear()
    {
    	log.setEditable(true);
		log.setText("");
		log.setEditable(false);
    }
    
    class FilteredStream extends FilterOutputStream 
	{
    	public FilteredStream(OutputStream aStream) 
    	{
        	super(aStream);
    	}

        public void write(byte b[]) throws IOException 
        {
            String aString = new String(b);
            append(aString);
        }

        public void write(byte b[], int off, int len) throws IOException 
        {
            String aString = new String(b , off , len);
            
            append(aString);
        }
    }
}
